/*Copyright (C) 2009 - 2011 MASSART GAUTHIER and Careil Baptiste

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "../headers.h"

/*
** Permet de compter le nombre d'occurence de key dans cs
*/
int str_count(const char *cs, const char key) {
	int count = 0, i = 0;

	while(cs[i] != '\0') {
		if(cs[i] == key) {
			count++;
		}

		i++;
	}

	return count;
}

/*
** Permet d'indenter d'un certain nombre d'espaces
*/
void indenter_espace(short nb_espaces) {
	short i;

	for(i = 0; i < nb_espaces; i++) {
		addch(' ');
	}
}

/*
** Permet d'indenter un texte
*/
void indenter(const char *cs, short nb_espaces, bool indenter_apres) {
	indenter_espace(nb_espaces);
	addstr(cs);

	if(indenter_apres) {
		indenter_espace(nb_espaces);
	}
}

/*
** Permet d'afficher centrer la chaine cs (n'ajoute pas de retour
** à la ligne '\n'). Attention, un retour à la ligne
** en milieu de chaine ne sera pas identé.
*/
int afficher_centre(const char *cs) {
	short lenght = strlen_utf8(cs);
	short debutTitre = DEFAULT_SCREEN_SIZE_X / 2 - lenght / 2;
	short y, x;
	getyx(stdscr, y, x);

	move(y, debutTitre);
	addstr(cs);
	goto_next_line();

	return debutTitre;
}

void afficher_barre_son(void) {
	short i = 0;
	CSLP_Color(COLOR_GREEN, COLOR_MAGENTA);
	goto_begin_line();
	save_cursor_pos();

	while(i != DEFAULT_SCREEN_SIZE_X) {
		addch(' ');
		i++;
	}

	restore_cursor_pos();
	addstr("\t\t      MUSIQUE : ");
	CSLP_Color(COLOR_CYAN, COLOR_MAGENTA);

	if(is_music_stoped())
		addstr("ARRET ");
	else
		addstr("MARCHE");

	CSLP_Color(COLOR_GREEN, COLOR_MAGENTA);
	addstr("  │  VOLUME MUSIQUE-SONS : ");
	CSLP_Color(COLOR_CYAN, COLOR_MAGENTA);
	printw(" %ld-%ld", volume_musique, volume_son);

	CSLP_Color(COLOR_GREEN, COLOR_MAGENTA);
	addstr("  │  MODE DE LECTURE : ");
	CSLP_Color(COLOR_CYAN, COLOR_MAGENTA);

	if(is_music_looping())
		addstr("BOUCLE   ");
	else if(music_get_mode_shuffle())
		addstr("ALEATOIRE");
	else
		addstr("CONTINUE ");


	pmove(BAS, 1);
	goto_begin_line();
}

void actualiser_barre_son(void) {
	int y, x;
	getyx(stdscr, y, x);
	move(0, 0);
	afficher_barre_son();
	CSLP_Color(COLOR_BLACK, COLOR_BLACK);
	move(y, x);
	refresh();
}

/*
** Permet d'afficher le titre titre. Attention cette chaine ne doit
** pas comporter de retour à la ligne!
*/
void afficher_titre(const char *titre) {
	short i, j;
	afficher_barre_son();
	CSLP_Color(COLOR_YELLOW, COLOR_RED);
	goto_begin_line();
	save_cursor_pos();

	for(j = 0; j != 2; j++) {
		for(i = 0; i != DEFAULT_SCREEN_SIZE_X; i++) {
			addch(' ');
		}

		goto_next_line();
	}

	restore_cursor_pos();

	afficher_centre(titre);
	souligner_centre(strlen_utf8(titre));
	CSLP_Color(COLOR_BLACK, COLOR_BLACK);
	addch('\n');

}

void souligner_centre(short longueur_soulignage) {
	short i;
	short indentSoulignage;
	indentSoulignage = DEFAULT_SCREEN_SIZE_X - longueur_soulignage;
	indentSoulignage = ceil((float)(indentSoulignage) / 2.f);
	indenter_espace(indentSoulignage);

	for(i = indentSoulignage; i < DEFAULT_SCREEN_SIZE_X; i++) {
		if(i - indentSoulignage < longueur_soulignage) {
			addstr("¯");
		}
		else {
			addch(' ');
		}
	}
	pmove(BAS, 1);
}

/*
** Permet d'afficher le menu "recommencer?" à la fin d'un jeu.
*/
int afficher_menu_recommencer(const char *contenu_titre) {
	short choix = afficher_menu("Recommencer\nRevenir au menu du jeu\n", "Voulez-vous recommencer une partie ou revenir au menu du jeu?\n", contenu_titre);
	return choix;
}

/*
** Permet de demander le nom du joueur
*/
void get_player_name(short player_number, char player_name[]) {
	bool redemander = false;
	short retGetStr = 0, choix = 0;

	CSLP_ColorText(CT);

	do {
		redemander = false;
		addch('\n');

		if((player_number == 0 || player_number == 1)) {
			if(prenom[0] != '\0') {
				CSLP_ColorText(CT);
				addstr(" Le nom ");
				CSLP_ColorText(COLOR_RED);
				addstr(prenom);
				CSLP_ColorText(CT);
				addstr(" vous convient-il ?\n\n");
				choix = afficher_menu_simple("Oui\nNon\n");

				if(choix == 1) {
					retGetStr = strlen(prenom);
				}
				else {
					CSLP_ColorText(CT);

					if(player_number == 0)
						addstr("\n\n Quel est votre nom ? ");
					else {
						addstr("\n\n Quel est votre nom joueur ");
						CSLP_ColorText(COLOR_RED);
						printw("%i", player_number);
						CSLP_ColorText(CT);
						addstr(" ? ");
					}

					retGetStr = lire(player_name, MAX_PLAYER_NAME_LENGHT);
				}
			}
			else {
				CSLP_ColorText(CT);

				if(player_number == 0)
					addstr("\n\n Quel est votre nom ? ");
				else {
					addstr("\n\n Quel est votre nom joueur ");
					CSLP_ColorText(COLOR_RED);
					printw("%i", player_number);
					CSLP_ColorText(CT);
					addstr(" ? ");
				}

				retGetStr = lire(player_name, MAX_PLAYER_NAME_LENGHT);
			}
		}
		else {
			CSLP_ColorText(CT);
			addstr("\n Quel est votre nom joueur ");
			CSLP_ColorText(COLOR_RED);
			printw("%i", player_number);
			CSLP_ColorText(CT);
			addstr(" ? ");
			retGetStr = lire(player_name, MAX_PLAYER_NAME_LENGHT);
		}

		if(retGetStr > MAX_PLAYER_NAME_LENGHT) {
			printw("\n Votre nom dépasse la taille maximum de %i!!!\n", MAX_PLAYER_NAME_LENGHT);
			addstr(" Veuillez en spécifier un plus cours s'il vous plait.\n");
			redemander = true;
		}
		else if(retGetStr == 0) {
			addstr("\n Erreur de saisie. Veuillez recommencer s'il vous plait.\n");
			redemander = true;
		}
		else if(player_name[0] == '\0') {
			addstr("\n Je ne doute pas que vous trouverez un nom plus long.\n");
			redemander = true;
		}

		refresh();
	}
	while(redemander);

	modif_conf();
}

/*
** Efface l'ensemble de la ligne où est le curseur.
** Le curseur est ramené en début de ligne.
*/
void clear_line() {
	goto_begin_line();
	clrtoeol();
}

/*
** Efface les \n, \b et \r d'une ligne. S'ils y en a plusieurs
** de chaque, seulement les premiers trouvés seront supprimé.
*/
void remove_ret_line(char *str) {
	short i;
	char *to_remove;
	char *ret_line = "\n\b\r";

	for(i = 0; ret_line[i] != '\0'; i++) {
		to_remove = strchr(str, ret_line[i]);

		if(to_remove) {
			*to_remove = '\0';
		}
	}
}

/*
** Permet de demander confirmation d'une action à l'utilisateur
*/
bool confirm_str(const char *keyword, const char *title) {
	char *titre_menu;

	titre_menu = malloc(sizeof(char) * (strlen(keyword) + 29));
	sprintf(titre_menu, "Êtes-vous sûr de vouloir %s?", keyword);
	return (afficher_menu("Oui\nNon\n", titre_menu, title) == 1 ? true : false);
}

/*
** Permet d'afficher la touche passée en paramètre.
*/
void afficher_touche(short touche) {
	char str[4];

	if(touche == KEY_UP) {
		strcpy(str, "↑");
	}
	else if(touche == KEY_DOWN) {
		strcpy(str, "↓");
	}
	else if(touche == KEY_LEFT) {
		strcpy(str, "←");
	}
	else if(touche == KEY_RIGHT) {
		strcpy(str, "→");
	}
	else {
		sprintf(str, "%c", touche);
	}

	addstr(str);
}

/*
** Concatène `line' dans l'entrée menu `entry'
** `line' ne doit pas comporter de retour chariot
*/
void cat_line_in_entry(char **entry, const char *line) {
	if(*entry == NULL) {
		*entry = malloc((strlen(line) + 2) * sizeof(char));
		strcpy(*entry, line);
	}
	else {
		size_t entry_len = strlen_utf8(line) + strlen_utf8(*entry) + 2;
		*entry = realloc(*entry, entry_len * sizeof(char));
		strcat(*entry, line);
	}

	entry[0][strlen(*entry) + 1] = '\0';
	entry[0][strlen(*entry)] = '\n';
}

#ifndef __FreeBSD__
int strlcpy(char *dest, const char *src, int size) {
	int  i;

	i = 0;

	while(i < size - 1 && src[i] != '\0') {
		dest[i] = src[i];
		i++;
	}

	dest[i] = '\0';
	return (strlen(dest));
}
#endif

void *xmalloc(unsigned int size) {
	void *p;

	p = malloc(size);

	if(p == NULL) {
		Log_full(LOG_DEFAULT, "xmalloc(): ENOMEM Cannot allocate memory", 0);
		exit(1);
	}

	return (p);
}

int count_word(const char *str, short result, const char *c) {
	int i;
	int inc;

	i = 0;
	inc = 1;

	if(*str == '\0')
		return (result);

	while(strchr(c, str[i]) == NULL && str[i] != '\0')
		i++;

	if(i == 0)
		inc = 0;

	while(strchr(c, str[i]) != NULL && str[i] != '\0')
		i++;

	return (count_word(&str[i], result + inc, c));
}

void swt_fill(char **tab, const char *str, int idx, const char *c) {
	int i;
	int inc;

	i = 0;
	inc = 0;

	if(*str == '\0') {
		tab[idx] = NULL;
		return;
	}

	while(strchr(c, str[i]) == NULL && str[i] != '\0')
		i++;

	if(i > 0) {
		inc = 1;
		tab[idx] = xmalloc(i + 1);
		strlcpy(tab[idx], str, i + 1);
	}

	while(strchr(c, str[i]) != NULL && str[i] != '\0')
		i++;

	return (swt_fill(tab, str + i, idx + inc, c));
}

char **split(const char *separators, const char *str) {
	int word_count;
	char **word_tab;

	word_count = count_word(str, 0, separators);
	word_tab = xmalloc((word_count + 1) * sizeof(*word_tab));
	swt_fill(word_tab, str, 0, separators);
	return (word_tab);
}

void unsplit(char **tableau) {
	short i;
	for(i = 0; tableau[i] != NULL; i++) {
		free(tableau[i]);
	}

	free(tableau);
}

/*
**Remplace la fonction strlen_utf8 qui ne supporte pas les caractère UTF-8
*/
int strlen_utf8(const char *s) {
	int i = 0, j = 0;
	while(s[i]) {
		if((s[i] & 0xc0) != 0x80) j++;
		i++;
	}
	return j;
}
